package nio.groupchat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

/**
 * 群聊系统服务端
 */
public class GroupChatServer {
    private Selector selector;
    private ServerSocketChannel listenChannel;
    private static final int PORT = 6667;

    public GroupChatServer() throws IOException {
        /**
         * 得到选择器
         */
        selector = Selector.open();
        /**
         * 获取通道
         */
        listenChannel = ServerSocketChannel.open();
        /**
         * 绑定端口
         */
        listenChannel.socket().bind(new InetSocketAddress(PORT));
        /**
         * 设置非阻塞模式
         */
        listenChannel.configureBlocking(false);
        /**
         * 将listenChannel注册到selector
         */
        listenChannel.register(selector, SelectionKey.OP_ACCEPT);
    }

    /**
     * 监听
     */
    public void listen() throws IOException {
        while (true){
            int count = selector.select(2000);
            if (count > 0){
                /**
                 * 遍历select集合
                 */
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()){
                    SelectionKey key = iterator.next();
                    /**
                     * 监听连接事件
                     */
                    if (key.isAcceptable()){
                        SocketChannel socketChannel = listenChannel.accept();
                        /**
                         * 设置非阻塞
                         */
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector,SelectionKey.OP_READ);
                        System.out.println(socketChannel.getRemoteAddress()+ "  上线");
                    }
                    if (key.isReadable()){
                        readData(key);
                    }
                    /**
                     * 删除key
                     */
                    iterator.remove();
                }
            }
        }
    }

    private void readData(SelectionKey key){
        SocketChannel socketChannel = null;
        try {
            /**
             * 得到channel
             */
            socketChannel = (SocketChannel) key.channel();
            /**
             * 创建buffer
             */
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

            int count = socketChannel.read(byteBuffer);
            if (count > 0){
               String msg = new String(byteBuffer.array());
                System.out.println("接受客户端消息 "+msg);
                /**
                 * 向其他客户端转发消息
                 */
                sendInfo(msg,socketChannel);
            }
        }catch (Exception e){
            try {
                System.out.println(socketChannel.getRemoteAddress()+ "离线了");
                /**
                 * 取消注册
                 */
                key.cancel();
                /**
                 * 关闭通道
                 */
                socketChannel.close();
            }catch (IOException es){
                es.printStackTrace();
            }
        }
    }

    /**
     * 转发消息
     */
    private void sendInfo(String msg , SocketChannel self) throws IOException {
        System.out.println("服务器转发消息");
        /**
         * 遍历所有注册到selector的channel并排除自己
         */
        for (SelectionKey key : selector.keys()){
            /**
             * 取出对应的socketChannel
             */
            Channel targetChannel = key.channel();
            if (targetChannel instanceof SocketChannel && targetChannel != self){
                SocketChannel dest = (SocketChannel)targetChannel;
                /**
                 * 将消息放入缓冲区
                 */
                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
                /**
                 * 将buffer的数据写入channel
                 */
                dest.write(buffer);
            }
        }
    }

    public static void main(String[] args) throws IOException {
        /**
         * 创建一个服务器对象
         */
        GroupChatServer server = new GroupChatServer();
        server.listen();
    }
}
